<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>AdminLTE 3 | Vue3 | Layout</title>

  <!-- Google Font: Source Sans Pro -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
  <!-- Font Awesome Icons -->
  <link rel="stylesheet" href="plugins/fontawesome-free/css/all.min.css">
  <!-- Theme style -->
  <link rel="stylesheet" href="css/adminlte.min.css">
</head>
<body>
<div class="wrapper" id="app">

  <!-- 顶部页头 -->
  <lte-main-header>
	  <!-- 这里要写完整的标签，如果写简写的标签，只能渲染出一个组件，原因未知（可能是把第二个当成了结束标签了吧）-->
	  <lte-main-header-navbar-left></lte-main-header-navbar-left>
	  <!-- @sidebar-collapse 监听由控制面板按钮发出来的事件，对Sidebar进行显示或隐藏 -->
	  <lte-main-header-navbar-right @sidebar-collapse="collapseSidebar"></lte-main-header-navbar-right>
  </lte-main-header>

  <!-- 左侧菜单 -->
  <lte-main-sidebar @click.stop style="padding-bottom: 10px;">
	  <lte-main-sidebar-logo title="AdminLTE 3 + Vue3" logo="img/AdminLTELogo.png"></lte-main-sidebar-logo>
	  <lte-sidebar>
		  <lte-user-panel title="Alexander Pierce" logo="img/user2-160x160.jpg"></lte-user-panel>
		  <nav class="mt-2"><lte-treeview :items="menus"></lte-treeview></nav>
	  </lte-sidebar>
  </lte-main-sidebar>

  <!-- 工作区 -->
  <lte-main-content>
	  <div class="col-md-10 callout callout-info" style="margin-top: 20px;margin-left: 15px;">
		<h5>本节简介</h5>
		<ul>
		  <li>菜单打开与关闭的速度不同，用以展示动画的可控性</li>
		  <li>菜单中可以显示 NEW 标签，也可以显示消息数，消息数优先于 NEW 标签（互斥）</li>
		  <li>菜单Label （EXAMPLES、LABELS）</li>
		</ul>
	  </div>
	  
  </lte-main-content>
  
  <!-- 系统设置区 -->
  <lte-control-sidebar :style="{display:controlSidebarDisplay}"></lte-control-sidebar>

  <!-- 底部页脚 -->
  <lte-main-footer>
	  <lte-copy-right></lte-copy-right>
	  <lte-version></lte-version>
  </lte-main-footer>
  
  <!-- TODO: 需要考虑这个层的作用 -->
  <div id="sidebar-overlay"></div>
</div>
<!-- ./wrapper -->

<script src="https://unpkg.com/vue@3.0.11/dist/vue.global.js"></script>
<script src="https://unpkg.com/mitt/dist/mitt.umd.js"></script>
<script src="js/FullScreen.js"></script>
<script src="js/PushMenu.js"></script>
<script src="js/Logo.js"></script>
<script src="js/CopyRight.js"></script>
<script src="js/Version.js"></script>
<script src="js/ControlSidebar.js"></script>
<script src="js/MainSidebar.js"></script>

<script src="js/animations.js"></script>
<script src="js/menuData.js"></script>

<script type="text/javascript">
	if (!window.emitter) {
		window.emitter = mitt();
	}
	var menus = menus || [];
	const app = Vue.createApp({
		// 必须是函数形式
		data() {
			return {
				message: "Hello Vue!",
				menus: menus,
				// Sidebar的隐藏/显示动画效果是建立在display样式属性上的，
				// 因此必须事前设置该样式
				controlSidebarDisplay: 'none'
			}
		},
		beforeCreate() {
			// 阻止动画效果
			document.body.classList.add("hold-transition");
			// 最小化sidebar
			document.body.classList.add("sidebar-mini");
		},
		created() {
			// 完全模仿adminlte的作法，没搞明白这个样式为什么要先加上，而后再去掉
			document.body.classList.remove("hold-transition");
		},
		methods: {
			collapseSidebar() {
				if (!document.body.classList.contains("control-sidebar-slide-open")) {
					// 隐藏横向滚动条
					document.documentElement.classList.add("control-sidebar-animate");
					this.controlSidebarDisplay = 'block';
					setTimeout(function() {
						document.body.classList.add("control-sidebar-slide-open");
						setTimeout(function() {
							document.documentElement.classList.remove("control-sidebar-animate");
						},350)
					},10)
				} else {
					// 隐藏横向滚动条
					document.documentElement.classList.add("control-sidebar-animate");
					document.body.classList.remove("control-sidebar-slide-open");
					var that = this;
					setTimeout(function() {
						that.controlSidebarDisplay = 'none';
						document.documentElement.classList.remove("control-sidebar-animate");
					},350)
				}
			}
		}
	});
	
	app.component('lte-push-menu', PushMenu);
	app.component('lte-full-screen', FullScreent);
	app.component('lte-main-sidebar-logo', Logo);
	app.component('lte-copy-right', CopyRight);
	app.component('lte-version', Version);
	app.component('lte-control-sidebar', ControlSidebar);
	app.component('lte-main-sidebar', MainSidebar);
	
	app.component('lte-user-panel', {
		props: {
			title: {
				type: String,
				default: function() {
					return 'Alexander Pierce'
				}
			},
			logo: {
				type: String,
				default: function() {
					return 'img/user2-160x160.jpg'
				}
			}
		},
		template: `<div class="user-panel mt-3 pb-3 mb-3 d-flex">
		    <div class="image">
		      <img :src="logo" class="img-circle elevation-2" alt="User Image">
		    </div>
		    <div class="info">
		      <a href="#" class="d-block">{{title}}</a>
		    </div>
		  </div>`
	});
	
	app.component('lte-treeview', {
		props: {
			items: Array
		},
		data() {
			return {
				activeId: 2
			}
		},
		computed: {
			parentId() {
				for (var i = 0; i < this.items.length; i++) {
					var item = this.items[i];
					if (item.id == this.activeId) {
						return item.id;
					}
					if (item.children && item.children.length > 0) {
						for (var j = 0; j < item.children.length; j++) {
							var child = item.children[j];
							if (child.id == this.activeId) {
								return child.parentId;
							}
						}
					}
				}
				return null;
			}
		},
		methods: {
			menuSelect(event, id, url) {
				console.log(id, url, event);
				if (url && url.indexOf("http") === -1) {
					this.activeId = id;
					// TODO: 如果是使用Router，需要调用Router的API
					// 如果是使用a的跳转能力，则不能阻止默认事件的执行
					event.preventDefault();
				}
			}
		},
		template: `<ul class="nav nav-pills nav-sidebar nav-child-indent" data-widget="treeview" role="menu" data-accordion="false">
		      <template v-for="menu of items">
			  <lte-treeview-menu 
				:activeId="activeId" 
				:active="parentId == menu.id" 
				:opened="parentId == menu.id" 
				:menu="menu"
				@menu-select="menuSelect"></lte-treeview-menu>
			  </template>
		    </ul>`
	});
	
	app.component('lte-treeview-menu', {
		props: {
			menu: Object,
			active: {
				type: Boolean,
				default: function() {
					return false;
				}
			},
			activeId: Number | String,
			opened: {
				type: Boolean,
				default: function() {
					return false;
				}
			}
		},
		data() {
			return {
				// 菜单是否打开必须由此属性判断，否则视图更新时会丢失打开状态
				isOpen: this.opened
			}
		},
		methods: {
			toggle(event) {
				if (!this.menu.children || this.menu.children.length == 0) {
					return;
				}
				event.preventDefault();
				//console.log(this.$el.childNodes[1]); // li>ul
				const li = this.$el;
				var el = li.lastChild;
				
				//console.log("isOpen", this.isOpen);
				// el.offsetHeight 是关键值，等于0时表示当前是关闭状态
				if (this.isOpen) {
					var that = this;
					slideUp(el, {after: function() {
						el.style.overflow = "";
						el.style.height = "";
						li.classList.remove("menu-open");
						that.isOpen = false;
					}, speed: 150/*为了演示动画速度*/})
				} else {
					this.isOpen = true;
					// 仅依靠 isOpen变更来更新视图会有一个延时，所以这里直接将样式加上
					li.classList.add("menu-open");
					slideDown(el, {after: function() {
						el.style.overflow = "";
						el.style.height = "";
					}, speed: 500/*为了演示动画速度*/});
				}
			}
		},
		template: `<li :class="{
					'menu-open':isOpen,
					'nav-item': menu.type != 'label',
					'nav-header': menu.type == 'label'
				   }">
				<template v-if="menu.type == 'label'">{{menu.title}}</template>
		        <a :href="menu.url" :target="menu.target" class="nav-link" :class="active ? 'active':''"
				  @click.stop="toggle"
				  v-if="menu.type!='label'">
		          <i class="nav-icon" :class="menu.icon"></i>
		          <p>
		            {{menu.title}}
		            <i class="right fas fa-angle-left" v-if="menu.children != null && menu.children.length > 0"></i>
					<span class="right badge badge-danger" v-if="menu.isNew && !menu.messageCount">New</span>
					<span class="badge badge-info right" v-if="menu.messageCount > 0">{{menu.messageCount}}</span>
		          </p>
		        </a>
		        <ul class="nav nav-treeview" 
				  v-if="menu.type!='label' && menu.children != null && menu.children.length > 0">
		          <li class="nav-item" v-for="child of menu.children">
		            <a class="nav-link"
						:class="activeId == child.id ? 'active':''"
						:href="child.url"
						:target="child.target"
						@click="$emit('menuSelect',$event, child.id, child.url)">
		              <i class="nav-icon" :class="child.icon"></i>
		              <p>
						{{child.title}}
						<span class="right badge badge-danger" v-if="child.isNew">New</span>
					  </p>
		            </a>
		          </li>
		        </ul>
		      </li>`
	})
	
	app.component('lte-control-sidebar-button', {
		template: `<a class="nav-link" @click.prevent="$emit('toggleDisplay')" data-widget="control-sidebar" data-slide="true" href="#" role="button">
			  <i class="fas fa-th-large"></i>
			</a>`
	});
	
	app.component('lte-main-header', {
		template: `<nav class="main-header navbar navbar-expand navbar-white navbar-light" style="min-height:3.5rem;">
			<slot></slot>
		</nav>`
	});
	
	app.component('lte-main-header-navbar-left', {
		template: `<ul class="navbar-nav">
			  <!--d-none d-sm-inline-block 此组样式表示在窄屏（手机竖版）下隐藏-->
			  <li class="nav-item">
				<lte-push-menu/>
			  </li>
			</ul>`
	});
	
	app.component('lte-main-header-navbar-right', {
		methods: {
			onSidebarToggle() {
				// TODO 如何更好的传递到父组组件进行事件处理
				this.$emit('sidebarCollapse')
			}
		},
		template: `<ul class="navbar-nav ml-auto">
			  <li class="nav-item d-none d-sm-inline-block">
			    <lte-full-screen/>
			  </li>
			  <li class="nav-item">
			    <lte-control-sidebar-button @toggle-display="onSidebarToggle"/>
			  </li>
			</ul>`
	});
	
	app.component('lte-sidebar', {
		template: '<div class="sidebar"><slot><p style="color:white;">Menu</p></slot></div>'
	})
	
	app.component('lte-main-content', {
		template: `<div class="content-wrapper">
			<slot></slot>
		</div>`,
	});
	
	app.component('lte-main-footer', {
		template: `<footer class="main-footer" style="min-height:3.5rem;">
			<slot></slot>
		</footer>`,
	});
	
	// 挂载之前定义好组件，否则组件不生效
	const vm = app.mount('#app');
	console.log("it works!");
</script>
<style>
	/* 菜单选中时，父级菜单背景色渐显效果 */
	.sidebar-dark-primary .nav-sidebar>.nav-item>.nav-link.active, .sidebar-light-primary .nav-sidebar>.nav-item>.nav-link.active {
	    transition: background ease-in-out .3s, width ease-in-out .3s;
	}
</style>
</body>
</html>
